﻿#include "http.hpp"
#include "paramsparser.hpp"

#include <iostream>

using namespace leak;

#define MB / (1024 * 1024)

std::atomic_uint64_t g_connected{ 0 };
std::atomic_uint64_t g_qps{ 0 };
std::atomic_uint64_t g_recv{ 0 };

int         g_package = 16;
char*       g_data    = new char[g_package];
std::string g_url;
std::string g_host;
uint16_t    g_port = 0;

void ExampleHttpServer() {
    auto router = std::make_shared<net::http::Router>();

    router->RegisterHandler("/test", [](const net::http::Request& req, auto rsp) {
        rsp->body = std::move(req.body);

        rsp->Write();
    });

    net::http::NewHttpServer(
        std::make_shared<utils::SequenceContextPool>(1),
        "0.0.0.0",
        g_port,
        router);
}

void HttpClientDoRequest(std::shared_ptr<net::http::Client> client, std::shared_ptr<net::http::Request> req) {
    client->DoRequest(
        req,
        [client, req](const net::http::Response& rsp) {
            // std::cout << "Http response status: " << rsp.status_string << std::endl;
            // std::cout << "Http response body: " << rsp.body << std::endl;
            g_recv += rsp.body.length();
            g_qps++;
            HttpClientDoRequest(client, req);
        },
        [](std::string_view err) {
            std::cout << "client err: " << err << std::endl;
        });
}

void ExampleHttpClient(utils::ContextPool pool, size_t count) {
    for (int i = 0; i < count; i++) {
        auto request    = std::make_shared<net::http::Request>();
        request->method = "POST";
        request->path   = "/test";
        request->body.assign(g_data, g_package);

        auto client = net::http::Client::New(pool->Next(), g_url);
        client->set_keep_alive(true);
        HttpClientDoRequest(client, request);
    }
}

int main(int argc, char* argv[]) {
    ParamsParser parser(argc, argv);

    auto disable_server   = parser.GetParams<bool>("disable_server", false);
    auto disable_client   = parser.GetParams<bool>("disable_client", false);
    auto client_pool_size = parser.GetParams<int>("client_pool_size", 1);
    auto server_pool_size = parser.GetParams<int>("server_pool_size", 1);
    auto client_count     = parser.GetParams<int>("client_count", 1);
    g_url                 = parser.GetParams<std::string>("url", "127.0.0.1:3050");

    g_package = parser.GetParams<int>("package", g_package);

    auto urlpos = g_url.find(':');
    g_port      = std::atoi(g_url.substr(urlpos + 1).data());

    std::cout << client_pool_size << " | " << server_pool_size << " | " << client_count << " | " << g_package << std::endl;

    if (!disable_server)
        ExampleHttpServer();

    if (!disable_client) {
        auto pool = std::make_shared<utils::SequenceContextPool>(client_pool_size);
        ExampleHttpClient(pool, client_count);
        uint64_t last_recv = 0;
        uint64_t last_qps  = 0;
        while (true) {
            uint64_t recv = g_recv - last_recv;
            uint64_t qps  = g_qps - last_qps;

            std::cout << "connected: " << g_connected
                      << " | qps(W): " << (float)qps / 10000
                      << " | recv(MB): " << (float)recv MB
                      << std::endl;

            last_recv = g_recv;
            last_qps  = g_qps;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    } else {
        getchar();
    }

    return 0;
}